第 2 章:Docker 安全設定與管理
評估 Docker 的安全性
- 由核心的命名空間和控制組機制提供的容器內在安全
- Docker程式(特別是服務端)本身的抗攻擊性
- 核心安全性的加強機制對容器安全性的影響
核心命名空間
Docker 容器和 LXC 容器很相似,所提供的安全特性也差不多。當用 docker run
啟動一個容器時,在後臺 Docker 為容器建立了一個獨立的命名空間和控制組集合。
命名空間提供了最基礎也是最直接的隔離,在容器中執行的程式不會被執行在主機上的程式和其它容器發現和作用。
每個容器都有自己獨有的網路堆疊,意味著它們不能存取其他容器的 sockets 或介面。不過,如果主機系統上做了相應的設定,容器可以像跟主機互動一樣的和其他容器互動。當指定公共連接埠或使用 links 來連線 2 個容器時,容器就可以相互通訊了(可以根據設定來限制通訊的策略)。
從網路架構的角度來看,所有的容器透過本地主機的橋接器介面相互通訊,就像物理機器透過物理交換機通訊一樣。。
控制組
控制組是 Linux 容器機制的另外一個關鍵元件,負責實作資源的統計和限制。
它提供了很多有用的特性;以及確保各個容器可以公平地分享主機的記憶體、CPU、磁碟 IO 等資源;當然,更重要的是,控制組確保了當容器內的資源使用產生負載時不會連累主機系統。
盡管控制組不負責隔離容器之間相互存取、處理資料和程式,它在防止分散式阻斷服務(DDOS)攻擊方面是必不可少的。尤其是在多使用者的平台(比 如公有或私有的 PaaS)上,控制組十分重要。例如,當某些應用程式表現異常的時候,可以保證一致地正常執行和效能。
伺服端防護
執行一個容器或應用程式的核心是透過 Docker 服務端。Docker 服務的執行目前需要 root 權限,因此其安全性十分關鍵。
首先,確保只有可信的使用者才可以存取 Docker 服務。Docker 允許使用者在主機和容器間共享檔案夾,同時不需要限制容器的存取權限,這就容易讓容器突破資源限制。例如,惡意使用者啟動容器的時候將主機的根目錄/
映射到容器的 /host
目錄中,那麽容器理論上就可以對主機的檔案系統進行任意修改了。這聽起來很瘋狂?但是事實上幾乎所有虛擬化系統都允許類似的資源共享,而沒法禁止使用者共享主機根檔案系統到虛擬機系統。
這將會造成很嚴重的安全後果。因此,當提供容器建立服務時(例如透過一個 web 伺服器),要更加注意進行參數的安全檢查,防止惡意的使用者用特定參數來建立一些破壞性的容器
為了加強對服務端的保護,Docker 的 REST API(客戶端用來跟服務端通訊)在 0.5.2 之後使用本地的 Unix socket機制替代了原先綁定在 127.0.0.1 上的 TCP socket,因為後者容易遭受跨站腳本攻擊。現在使用者使用 Unix 權限檢查來加強socket的存取安全。
使用者仍可以利用 HTTP 提供 REST API 存取。建議使用安全機制,確保只有可信的網路或 VPN,或憑證保護機制(例如受保護的 stunnel 和 SSL 認證)下的存取可以進行。此外,還可以使用 HTTPS 和憑證來加強保護。
最近改進的 Linux 命名空間機制將可以實作使用非 root 使用者來執行全功能的容器。這將從根本上解決了容器和主機之間共享檔案系統而引起的安全問題。
終極目標是改進 2 個重要的安全特性:
- 將容器的 root 使用者映射到本地主機上的非 root 使用者,減輕容器和主機之間因權限提升而引起的安全問題
- 允許 Docker 服務端在非 root 權限下執行,利用安全可靠的子行程來代理執行需要特權權限的操作。這些子行程將只允許在限定範圍內進行操作,例如僅僅負責虛擬網路設定或檔案系統管理、設定操作等
最後,建議採用專用的伺服器來執行 Docker 和相關的管理服務(例如管理服務比如 ssh 監控和程式監控、管理工具 nrpe、collectd 等)。其它的業務服務都放到容器中去執行。
核心能力機制
能力機制(Capability)是 Linux 核心一個強大的特性,可以提供細緻的權限存取控制。 Linux 核心自 2.2 版本起就支援能力機制,它將權限劃分為更加細緻的操作能力,既可以作用在程式上,也可以作用在檔案上。
例如,一個 Web 服務程式只需要綁定一個低於 1024 的連接埠的權限,並不需要 root 權限。那麽它只需要被授權 net_bind_service
能力即可。此外,還有很多其他的類似能力來避免程式取得 root 權限。
預設情況下,Docker 啟動的容器被嚴格限制只允許使用核心的一部分能力。
使用能力機制對加強 Docker 容器的安全有很多好處。通常,在伺服器上會執行一堆需要特權權限的程式,包括有 ssh、cron、syslogd、硬體管理工具模組(例如負載模組)、網路設定工具等等。容器跟這些程式是不同的,因為幾乎所有的特權程式都由容器以外的支援系統來進行管理。
- ssh 存取被主機上ssh服務來管理
- cron 通常應該作為使用者程式執行,權限交給使用它服務的應用來處理
- 日誌系統可由 Docker 或第三方服務管理
- 硬體管理無關緊要,容器中也就無需執行 udevd 以 及類似服務
- 網路管理也都在主機上設定,除非特殊需求,容器不需要對網路進行設定
從上面的例子可以看出,大部分情況下,容器並不需要“真正的” root 權限,容器只需要少數的能力即可。為了加強安全,容器可以禁用一些沒必要的權限。
- 完全禁止任何 mount 操作
- 禁止直接存取本地主機的socket
- 禁止存取一些檔案系統的操作,比如建立新的設備、修改檔案屬性等
- 禁止模組載入
這樣,就算攻擊者在容器中取得了 root 權限,也不能獲得本地主機的較高權限,能進行的破壞也有限。
預設情況下,Docker採用 白名單 機制,禁用 必需功能 之外的其它權限。 當然,使用者也可以根據自身需求來為 Docker 容器啟用額外的權限。
其他安全特性
除了能力機制之外,還可以利用一些現有的安全機制來增強使用 Docker 的安全性,例如 TOMOYO 、 AppArmor 、 SELinux 、 GRSEC 等。
Docker 當前預設只啟用了能力機制。使用者可以採用多種方案來加強 Docker 主機的安全,例如:
在核心中啟用 GRSEC 和 PAX,這將增加很多編譯和執行時的安全檢查;透過位址隨機化避免惡意探測等。並且,啟用該特性不需要 Docker 進行任何設定。
使用一些有增強安全特性的容器模板,比如帶 AppArmor 的模板和 Redhat 帶 SELinux 策略的模板。這些模板提供了額外的安全特性。
使用者可以自訂存取控制機制來定制安全策略。
跟其它新增到 Docker 容器的第三方 工具一樣(比如網路拓撲和檔案系統共享),有很多類似的機制,在不改變 Docker 核心情況下就可以強化現有的容器。